#ifndef __MCS__STRING_FUNCTION_COLLECTION__HPP
#define __MCS__STRING_FUNCTION_COLLECTION__HPP

#include "FunctionFactory.hpp"
#include "InvalidArgumentException.hpp"

/// Collection of the string processing functions
class StringFunctionCollection : public FunctionCollection
{
public:
	//TODO:
	/*
	str chop(str val, int n);
	int length(str val);
	str truncate(str val, int n);
	str resize(str val, int n);
	str resize(str val, int n, str fill);
	str leftJustify(str val, int n);
	str leftJustify(str val, int n, str fill);
	str leftJustify(str val, int n, bool trunc);
	str leftJustify(str val, int n, str fill, bool trunc);
	str rightJustify(str val, int n);
	str rightJustify(str val, int n, str fill);
	str rightJustify(str val, int n, bool trunc);
	str rightJustify(str val, int n, str fill, bool trunc);
	str insert(str val, int pos, str ins);
	str remove(str val, int pos, int count);
	str simplify(str);
	str trim(str);
	str trimLeft(str);
	str trimRight(str);
	str lower(str);
	str upper(str);
	str replace(str val, int pos, int count, str ins);
	str replace(str val, str before, str after);
	str replace(str val, str before, str after, bool cs);

	int compare(str a, str b, bool cs);
	bool startsWith(str a, str b);
	bool startsWith(str a, str b, bool cs);
	bool endsWith(str a, str b);
	bool endsWith(str a, str b, bool cs);
	int find(str a, str b);
	int find(str a, str b, bool cs);
	int find(str a, str b, int from);
	int find(str a, str b, int from, bool cs);
	int findLast(str a, str b);
	int findLast(str a, str b, bool cs);
	int findLast(str a, str b, int from);
	int findLast(str a, str b, int from, bool cs);
	bool contains(str val, str ins);
	bool contains(str val, str ins, bool cs);
	int count(str val, str ins);
	int count(str val, str ins, bool cs);
	str char(str val, int pos);

	int ascii(str);
	str char(int);

	int checkInt(str);
	int checkReal(str);
	int checkBool(str);
	bool isInt(str);
	bool isReal(str);
	bool isBool(str);
	int  toInt(str);
	real toReal(str);
	bool toBool(str);
	*/
	virtual void registerFunctions(FunctionFactory * factory)
	{
		factory->insertFunction("left", &functionLeft);
		factory->insertFunction("right", &functionRight);
		factory->insertFunction("mid", &functionMid1);
		factory->insertFunction("mid", &functionMid2);
	}
private:
	static String functionLeft(String src, int n)
	{
		if(n < 0)
			throw InvalidArgumentException("left(str,int)", 2, "count", new IntValue(n), "Cannot be negative");
		if(size_t(n) > src.size())
			throw InvalidArgumentException("left(str,int)", 2, "count", new IntValue(n), "Cannot be greater than string size");
		if(n == 0) return String();
		if(n == src.size()) return src;
		return src.substr(1, n);
	}

	static String functionRight(String src, int n)
	{
		if(n < 0)
			throw InvalidArgumentException("right(str,int)", 2, "count", new IntValue(n), "Cannot be negative");
		if(size_t(n) > src.size())
			throw InvalidArgumentException("right(str,int)", 2, "count", new IntValue(n), "Cannot be greater than string size");
		if(n == 0) return String();
		if(n == src.size()) return src;
		return src.substr(src.size() - n, n);	
	}

	static String functionMid1(String src, int n)
	{
		if(n < 0)
			throw InvalidArgumentException("mid(str,int)", 2, "pos", new IntValue(n), "Cannot be negative");
		if(size_t(n) > src.size())
			throw InvalidArgumentException("mid(str,int)", 2, "pos", new IntValue(n), "Cannot be greater than string size");
		if(n == 0) return src;
		if(n == src.size()) return String();
		return src.substr(n, src.size() - n);
	}

	static String functionMid2(String src, int n, int k)
	{
		if(n < 0)
			throw InvalidArgumentException("mid(str,int,int)", 2, "pos", new IntValue(n), "Cannot be negative");
		if(size_t(n) > src.size())
			throw InvalidArgumentException("mid(str,int,int)", 2, "pos", new IntValue(n), "Cannot be greater than string size");
		if(k < 0)
			throw InvalidArgumentException("mid(str,int,int)", 2, "count", new IntValue(k), "Cannot be negative");
		if(size_t(k) > src.size() - size_t(n))
			throw InvalidArgumentException("mid(str,int,int)", 2, "count", new IntValue(k), "Cannot be greater than length of the available string portion");
		return src.substr(n, k);
	}
};

#endif //__MCS__STRING_FUNCTION_COLLECTION__HPP
